【PHP】クラスメソッド(static) - クラスレベルのメソッド

【PHP】クラスメソッド(static) - クラスレベルのメソッド

クラスにはクラスメソッドと呼ぶメソッドがあります。

クラスメソッドはクラスレベルのメソッドで、同じクラスのオブジェクト間で共通のメソッドになります。

ここでは、クラスメソッドについて解説します。

検証環境

クラスメソッド

クラスメソッドは“クラスレベルのメソッド”です。

クラスに紐づくため、オブジェクトを生成しなくても使用可能なメソッドになります。

また、クラスメソッドはオブジェクトを前提としないため、オブジェクト自身を表す擬似変数$thisは使用できません。

そのため、オブジェクトのメソッドからクラスメソッドを呼び出すことができますが、フィールドやメソッドのアクセスはできないことに注意が必要です。

クラスメソッドの定義

クラスメソッドは使用するには定義が必要です。

基本構文

class クラス名 {
    アクセス修飾子 static function クラスメソッド名( 仮引数1, 仮引数2 ... ) {
        処理
        return 戻り値;
    }
}

クラスメソッドは通常のメソッドの構文に加えて、アクセス修飾子とfunctionの間にstaticキーワードを記述します。

サンプル

<?php

// 人間クラス
class Person {
    
    ___ih_hl_start
    public static function greeting() {
        echo "Hello.\n";
    }
    ___ih_hl_end
    
}

?>
$ php sample.php
$

6〜8行目がクラスメソッドの定義です。

クラスメソッドの呼び出し

クラスメソッドを実行するには、関数やメソッドと同様に呼び出しを行います。

基本構文

クラス名::クラスメソッド名(実引数1, 実引数2 ...)

クラス名とクラスメソッド名をダブルコロン(::)で繋いで記述します。

引数がある場合は、丸括弧(())内に実引数を記述してください。

サンプル

<?php

// 人間クラス
class Person {
    
    public static function greeting() {
        echo "Hello.\n";
    }
    
}

___ih_hl_start
Person::greeting();
___ih_hl_end

?>
$ php sample.php
Hello

12行目がクラスメソッドの呼び出しです。

Personクラスのgreetingクラスメソッドを呼び出しています。

実行結果にHelloの出力があることから、正常に処理されたことが分かります。

オブジェクトの共通メソッド

クラスメソッドはオブジェクトのメソッドから呼び出すことが可能です。

<?php

// 人間クラス
class Person {
    
    public $name;
    
    public function __construct( $n ) {
        $this->name = $n;
    }
    
    public static function greeting() {
        echo "Hello.\n";
    }
    
    public function message() {
        ___ih_hl_start
        Person::greeting();
        ___ih_hl_end
        echo 'My name is ' . $this->name . ".\n";
    }
    
}

$person1 = new Person('TANAKA');
$person2 = new Person('SUZUKI');

$person1->message();
$person2->message();

?>
$ php sample.php
Hello.
My name is TANAKA.
Hello.
My name is SUZUKI.

ただし、冒頭で説明した通り、クラスメソッドはクラスに紐づくメソッドであり、オブジェクトを前提としないため、擬似変数$thisは使用できません。

<?php

// 人間クラス
class Person {
    
    public $name;
    
    public function __construct( $n ) {
        $this->name = $n;
    }
    
    public static function greeting() {
        echo "Hello.\n";
        ___ih_hl_start
        echo 'My name is ' . $this->name . ".\n";
        ___ih_hl_end
    }
    
}

$person = new Person('TANAKA');

$person->greeting();

?>
$ php sample.php
Hello.
PHP Fatal error:  Uncaught Error: Using $this when not in object context in sample.php:14
Stack trace:
#0 sample.php(21): Person::greeting()
#1 {main}
  thrown in sample.php on line 14

このようにクラスメソッドから擬似変数$thisにアクセスするとエラーが発生します。

注意点

PHPではオブジェクトからクラスメソッドを実行できます。

しかし、そのようなコードは複雑化や処理目的の誤解を招くため、推奨されません。

例えば次のコードはオブジェクトからクラスメソッドを呼び出しています。

<?php

// 人間クラス
class Person {
    
    public static function greeting() {
        echo "Hello.\n";
    }
    
}

$person = new Person();

___ih_hl_start
$person->greeting();
___ih_hl_end

?>
$ php sample.php
Hello.

14行目のみを見た場合、greetingメソッドはオブジェクトとクラスのどちらのメソッドか判別できません。

このようなケースを避けるため、クラスメソッドは、クラス経由で呼び出すようにしましょう。

<?php

// 人間クラス
class Person {
    
    public static function greeting() {
        echo "Hello.\n";
    }
    
}

___ih_diff_start
-$person->greeting();
+Person::greeting();
___ih_diff_end

?>
$ php sample.php
Hello.

演習問題

問題1

次の実行結果になる車クラスを扱うプログラムを作成してください。
なお、下記条件を満たすものとします。

  • 車クラスを作成する
  • 車クラスのフィールドはナンバー、色、乗車人数とする
  • 車クラスのインスタンスの初期値はコンストラクタで設定する
  • 車情報を出力するinfoメソッドを作成する
  • タイヤ数を出力するtires_infoメソッドを作成する
    ※ tires_infoはクラスメソッドとします。
===== 車情報 =====
ナンバー : 1234
色    : 紺色
乗車人数 : 5人
タイヤ数 : 4個
===== 車情報 =====
ナンバー : 0987
色    : 赤
乗車人数 : 2人
タイヤ数 : 4個

問題2

次の実行結果になる家クラスを扱うプログラムを作成してください。
なお、下記条件を満たすものとします。

  • 家クラスを作成する
  • 家クラスのフィールドは面積(単位:畳)とする
  • 家クラスのインスタンスを3つ生成し、各面積(畳)は次の通りとする
    1つ目 : 6
    2つ目 : 14
    3つ目 : 30
  • 家クラスのインスタンスの初期値はコンストラクタで設定する
  • 畳の高さ(1.82m)と横幅(0.91m)を記憶するクラス変数を定義する
  • 1畳あたりの平方メートルを戻り値として返すarea_per_tatamiメソッドを作成する。
    ※ area_per_tatamiはクラスメソッドとします。
  • area_per_tatamiメソッドを使って家の面積(平方メートル)を出力するareaメソッドを作成する
面積 : 9.9372平方メートル
面積 : 23.1868平方メートル
面積 : 49.686平方メートル